package com.broada.apm.protocol;

import java.io.File;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.broada.apm.ApmServer;
import com.broada.apm.common.util.ZipUtil;
import com.broada.apm.indicator.api.AnalyzerService;
import com.broada.apm.indicator.api.ApmClientFactory;
import com.broada.apm.indicator.api.ConfigItemService;
import com.broada.apm.indicator.api.DimensionService;
import com.broada.apm.indicator.api.IndicatorItemService;
import com.broada.apm.indicator.api.L7ModuleService;
import com.broada.apm.indicator.api.L7moduleMenuService;
import com.broada.apm.indicator.api.ServiceService;
import com.broada.apm.indicator.api.common.ApmDataIndicatorException;
import com.broada.apm.model.Analyzer;
import com.broada.apm.model.DictMetrics;
import com.broada.apm.model.Dimension.Error;
import com.broada.apm.model.FilterRule;
import com.broada.apm.model.L7ModuelPanel;
import com.broada.apm.model.L7Module;
import com.broada.apm.model.L7moduleMenu;
import com.broada.apm.model.L7moduleMenuitem;
import com.broada.apm.model.L7moduleMetric;
import com.broada.apm.model.RemoteProtocolInfo;
import com.broada.apm.model.Service;
import com.broada.apm.protocol.L7ModuleParser.L7ModuleDescr;
import com.broada.apm.utils.ApmFileUtils;
import com.broada.apm.utils.ExceptionUtils;
import com.broada.apm.utils.IPUtils;
import com.google.common.collect.Maps;

/**
 * L7模块与协议分析器对接管理类
 *
 * 
 * @author louyi Create By 2015年4月2日 下午2:31:05
 */
public class L7ModuleManager {
	
	private static Logger log = LoggerFactory.getLogger(L7ModuleManager.class);

	private static L7ModuleService l7ModuleService = ApmClientFactory.getApmClient().getL7ModuleService();

	private static DimensionService dimensionService = ApmClientFactory.getApmClient().getDimensionService();
	
	private static ServiceService serviceService = ApmClientFactory.getApmClient().getServiceService();
	
	private static ConfigItemService configItemService = ApmClientFactory.getApmClient().getConfigItemService();
	
	private static IndicatorItemService indicatorItemService = ApmClientFactory.getApmClient().getIndicatorItemService();
	
	private static L7moduleMenuService l7moduleMenuService = ApmClientFactory.getApmClient().getL7moduleMenuService();
	
	private static AnalyzerService analyzerService = ApmClientFactory.getApmClient().getAnalyzerService();
	
	private static String MODULEXML = "module.xml";
	private static String FILESUFFIX = ".mod";

	/**
	 * 模块解析+存储+协议接口通知
	 * 
	 * @param file
	 * @throws Exception
	 */
	public static L7ModuleDescr resolveL7Module(File file) throws ApmDataIndicatorException {
		L7ModuleDescr l7Module = null;
		try {
			// 解压
			String tempDir = file.getParent() + "/" + file.getName().substring(0, file.getName().lastIndexOf("."));
			ZipUtil.unZip(file.getAbsolutePath(), tempDir, false, true);
			// 解析
			l7Module = L7ModuleParser.parse(tempDir + "/" + MODULEXML);
			// 模块版本验证
			validateVersion(l7Module.module.getCompatible());
			FileUtils.deleteDirectory(ApmFileUtils.getAbsoluteFile(tempDir));
		} catch (ApmDataIndicatorException e) {
			throw e;
		} catch (Exception e) {
			ExceptionUtils.error(log, "模块解析失败,请联系供应商获取正确的mod文件...", e);
			throw new ApmDataIndicatorException("模块解析失败,请联系供应商获取正确的mod文件...", e);
		}
		return l7Module;
	}
	
	public static void saveL7Module(L7ModuleDescr l7, File file) throws Exception {
		saveL7Module(l7);    // 数据库l7module相关处理
		// 服务器端留下副本
		File destDir = new File(ApmServer.L7_MODULE_DIR + "/" + l7.module.getL7_proto() + "/" + l7.module.getVersion());
        ZipUtil.unZip(file.getAbsolutePath(), destDir.getAbsolutePath(), false, false);
        new Thread(new Runnable() {
			@Override
			public void run() {
				try{
					List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();    //查询已经存在的协议分析器信息
					if(analyzers != null && analyzers.size() > 0){
						// 通知协议分析器增加模块
						String server_add = "";
						for(Analyzer analyzer : analyzers){
							server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
							RemoteProtocolInfo info = new RemoteProtocolInfo();
							info.setId(UUID.randomUUID().toString());   //UUID
							info.setL7_proto(l7.module.getL7_proto());
							info.setProto_name(l7.module.getCname());
							info.setAnalyzerId(analyzer.getId());
							info.setCallTime(Calendar.getInstance().getTime());
							RemoteProtocolInfo rpi = l7ModuleService.queryRemoteProtocolInfo(info);
							info.setVersion(l7.module.getVersion());
							// 如果该协议分析器由于某些原因，未能停止以前的该协议，即禁用失败
							if(rpi != null && (rpi.getStatus() == RemoteProtocolInfo.DISABLE_ERROR)){
								continue ;
							}
							// 旧版本已经禁用
							if(rpi != null && (rpi.getStatus() == RemoteProtocolInfo.DISABLE_SUCCESS 
									        || rpi.getStatus() == RemoteProtocolInfo.INSTALL_SUCCESS 
									        || rpi.getStatus() == RemoteProtocolInfo.INSTALL_ERROR)){
								info.setVersion(l7.module.getVersion());
							}
							ZeroClient client = new ZeroClient();
							client.connect(server_add);
							try{  // module_addremote 返回true 或者 抛异常
								if(client.module_uploadremote(l7.module.getL7_proto(), file.getAbsolutePath())){
									client.commit();
									info.setStatus(RemoteProtocolInfo.INSTALL_SUCCESS);    // 1安装成功
									info.setErrorMessage("安装协议成功");
								}
							} catch(Exception e){
								info.setStatus(RemoteProtocolInfo.INSTALL_ERROR);        // 2安装失败
								info.setErrorMessage("安装协议失败" + e.getMessage());
							}
							client.close();
							// 记录安装日志信息
							if(rpi == null){
								l7ModuleService.addRemoteProtocolInfo(info);
							}else{
								l7ModuleService.updateRemoteProtocolInfo(info);
							}
						}
					}
				}catch(Exception e){
					ExceptionUtils.error(log, "查询协议分析器信息异常...", e);
				}
			}
		}).start();
	}
	
	public static void saveL7Module(L7ModuleDescr l7) throws Exception {
		if(l7ModuleService.getL7ModuleById(l7.module.getId())!=null) {
	    	l7.module.setUpdateTime(new Date());
	        l7ModuleService.updateL7Module(l7.module);
	    } else {
	        l7ModuleService.addL7Module(l7.module);
	    }
	    for(Error err:l7.errortable) {
	        dimensionService.deleteError(err);
	        dimensionService.addError(err);
	    }
	    Collections.sort(l7.metrics,(m1,m2)->{
            return m1.getLayer() - m2.getLayer();
	    });
	    HashMap<String, DictMetrics> code2dictmetric = Maps.newHashMap();
	    if(StringUtils.isNotEmpty(l7.metricBase)) {
	        List<DictMetrics> baseMetrices = indicatorItemService.getDictMetricsByProtocol(Integer.parseInt(l7.metricBase));
	        for (DictMetrics m : baseMetrices) {
                code2dictmetric.put(m.getCode(), m);
            }
	    }
	    
	    for(L7moduleMetric m : l7.metrics) {
	        String[] path = StringUtils.split(m.getCode(),"/");
            if(path.length > 1 ) {
                String parentCode = StringUtils.join(ArrayUtils.remove(path, path.length-1),"/");
                DictMetrics parent = code2dictmetric.get(parentCode);
                m.setParentId(parent.getId());
	        }
	        DictMetrics old = indicatorItemService.getDictMetricsByCode(m.getCode());
	        if(old == null) {
    	        indicatorItemService.addDictMetrics(m);
    	        old = indicatorItemService.getDictMetricsByCode(m.getCode());
	        } else {
	        	indicatorItemService.updateDictMetrics(m);
	        }
            m.setId(old.getId());
            m.setMetricId(old.getId());

	        code2dictmetric.put(m.getCode(), m);
	        if(StringUtils.isNotEmpty(m.getMetricCaption())) {
	        	if(indicatorItemService.getL7ModuleMetric(m).size() <= 0) {
	        		indicatorItemService.addL7ModuleMetric(m);
	        	} else {
	        		indicatorItemService.updateL7ModuleMetric(m);
	        	}
	        }
	    }
	    for(L7ModuelPanel panel : l7.panels) {
	        panel.setMetricId(code2dictmetric.get(panel.getMetricCode()).getId());
	        if(indicatorItemService.getL7ModulePanel(panel).size() <= 0) {
	            indicatorItemService.addL7ModulePanel(panel);
	        } else {
	        	indicatorItemService.updateL7ModulePanel(panel);
	        }
	    }
	    Map<String,L7moduleMenu> menuname2menu = Maps.newHashMap();
	    l7moduleMenuService.deleteL7MenuByModuleId(l7.module.getId());    // 删除已有的模块menu
	    for(L7moduleMenu menu : l7.menus) {
	        if(l7moduleMenuService.getL7moduleMenu(menu).size() <= 0 ) {
	            l7moduleMenuService.addL7moduleMenu(menu);
	        } else {
	        	l7moduleMenuService.updateL7moduleMenu(menu);
	        }
	        menu.setId(l7moduleMenuService.getL7moduleMenu(menu).get(0).getId());
	        menuname2menu.put(menu.getCaption(), menu);
	    }
	    for(L7moduleMenu menu : l7.menus) {
	        for(L7moduleMenuitem item : menu.getMenuItems()){
	            item.setMenuId(menu.getId());
	            if(item.getMetricCode() != null) {
	                item.setMetricId(code2dictmetric.get(item.getMetricCode()).getId());
	            }
	            if(menuname2menu.containsKey(item.getOpenMenuName())){
	                item.setOpenMenu(menuname2menu.get(item.getOpenMenuName()).getId());
	            }
	            l7moduleMenuService.addL7moduleMenuitem(item);
	        }
	    }
	}
	
	/**
	 * 模块版本与协议分析器框架版本验证 简单实现
	 * 
	 * 兼容版本 从前到后 3段，不足3段的最后一位忽略 对于x的，全部不检查版本 对于数字，检查 2.x.x 匹配 2.0.2 2.1.0 2.2.0
	 * 2.2.x 匹配 2.2.1 2.2.2
	 *
	 * @param mversion
	 * @throws Exception 
	 */
	public static void validateVersion(String mversion) throws Exception {
		if (StringUtils.isNotEmpty(mversion)) {
			List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
			for(Analyzer analyzer : analyzers){
				String server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
				String pro_version = getProtocolVersion(server_add);
				String[] pro_array_version = pro_version.split("\\.");// 注意此处为正则匹配，不能用"."；
				String[] mod_array_version = mversion.split("\\.");
				int mod_length = mod_array_version.length;
				int pro_length = pro_array_version.length;
				if (mod_length > pro_length)
					throw new ApmDataIndicatorException("导入模块版本[" + mversion + "]不适用于协议分析主版本[" + pro_version + "]");
				int idx = 0;
				int minLength = Math.min(mod_length, pro_length);// 取最小长度值
				while (idx < minLength) {
					String _mversion = mod_array_version[idx];
					String _proversion = pro_array_version[idx];
					if (!isNumeric(_mversion) && !"x".equals(_mversion.toLowerCase())) {
						throw new ApmDataIndicatorException("导入模块版本[" + mversion + "]无法识别");
					} else if (isNumeric(_mversion)) {
						if (_mversion.compareTo(_proversion) != 0)
							throw new ApmDataIndicatorException("导入模块版本[" + mversion + "]不适用于协议分析主版本[" + pro_version + "]");
					}
					++idx;
				}
			}
		} else {
			throw new ApmDataIndicatorException("导入模块文件module.xml属性compatible不能为空");
		}
	}

	public static List<L7Module> queryL7Module() {
		List<L7Module> l7modules = null;
		l7modules = l7ModuleService.getAllL7Modules();
//        String protos = l7_protos();
//        log.info("协议分析器端正在运行的模块：" + protos);
//        protos = protos+",";
//        for (int i = 0; i < l7modules.size(); i++) {
//        	L7Module l7Module = l7modules.get(i);
//        	String l7_proto = String.valueOf("="+l7Module.getL7_proto()+",");
//        	if (protos.indexOf(l7_proto) > -1)
//        		l7Module.setStatus(Status.ENABLED.getVallue());
//        	else
//        		l7Module.setStatus(Status.DISABLED.getVallue());
//        	l7ModuleService.updateL7Module(l7Module);
//        }
		return l7modules;
	}

	/**
	 * 从协议分析器端获取正在运行的模块
	 * 
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private static String l7_protos() {
		StringBuilder str = new StringBuilder();
		
		try (ZeroClient client = new ZeroClient()){
			client.connect(ZeroClient.DEFAULT_SERVER_ADDR);
			String module = client.print_moduleconfig();
			if (module != null) {
				String modules[] = module.split("\n");
				for (String _module : modules) {
					if (_module.indexOf("l7_proto=") > -1) {
						String trim = _module.trim();
						String[] trims = trim.split("\t");
						if (trims != null) {
							str.append(trims[0] + ",");
						}
					}
				}
			}
		} catch (Exception e) {
			ExceptionUtils.error(log, e.getMessage(), e);
		}
		return str.toString();
	}

	/**
	 * 判断是否为数字
	 * 
	 * @param str
	 * @return
	 */
	private static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		return pattern.matcher(str).matches();
	}

	/**
	 * L7模块导出
	 * 
	 * @param l7_proto
	 * @param name
	 * @return
	 * @throws Exception
	 */
	public static File exportL7Module(int l7_proto, String name) throws Exception {
		L7Module l7module = l7ModuleService.getL7ModuleById(String.valueOf(l7_proto));
		String tempPath = FileUtils.getTempDirectory().getAbsolutePath();
		String fileName = name + FILESUFFIX;
		String destPath = tempPath + "/" + fileName;
		String zipPath = ApmServer.L7_MODULE_DIR + l7_proto + "/" + l7module.getVersion();

		// 遍历模块下面的文件夹，可能有删除模块后重新上传的
		File dirs = new File(ApmServer.L7_MODULE_DIR + l7_proto);
		for (File childFile : dirs.listFiles()) {
			String filename = childFile.getName();
			long temp = 0l;
			if (filename.trim().length() > l7module.getVersion().trim().length()) {
				filename = filename.substring(l7module.getVersion().length(), filename.length());
				temp = Long.valueOf(filename) > temp ? Long.valueOf(filename) : temp;
				zipPath = ApmServer.L7_MODULE_DIR + l7_proto + "/" + childFile.getName();
			}
		}
		ZipUtil.zip(zipPath, destPath, null);
		return ApmFileUtils.getAbsoluteFile(destPath);
	}

	/**
	 * L7模块的启用
	 * 
	 * @param L7_protoc
	 * @throws Exception
	 */
	public static void enabledL7Module(String l7_protoc) throws Exception {
		L7Module l7module = l7ModuleService.getL7ModuleById(l7_protoc);
//		// 遍历模块下面的文件夹，可能有删除模块后重新上传的
//		File dirs = new File(ApmServer.L7_MODULE_DIR + l7_protoc);
//		if (dirs.listFiles() != null && dirs.listFiles().length > 1) {
//			int j = 0;
//			for (int i=1; i<dirs.listFiles().length; i++) {
//				int length = dirs.listFiles()[i].getName().compareTo(dirs.listFiles()[j].getName());
//				if (length > 0) {
//					destDir = ApmServer.L7_MODULE_DIR + l7_protoc + "/" + dirs.listFiles()[i].getName() + "/" + MODULEXML;
//					j = i;
//				} else {
//					destDir = ApmServer.L7_MODULE_DIR + l7_protoc + "/" + dirs.listFiles()[j].getName() + "/" + MODULEXML;
//				}
//			} 
//		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try{
					// 通知协议分析器增加模块
//					File file = ApmFileUtils.getAbsoluteFile(destDir);
					List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
					String server_add = "";
					if(analyzers != null && analyzers.size() > 0){
						for(Analyzer analyzer : analyzers){
							ZeroClient client = new ZeroClient();
							server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
							client.connect(server_add);
							
							RemoteProtocolInfo info = new RemoteProtocolInfo();
							info.setId(UUID.randomUUID().toString());
							info.setL7_proto(l7module.getL7_proto());
							info.setVersion(l7module.getVersion());
							info.setAnalyzerId(analyzer.getId());
							info.setCallTime(Calendar.getInstance().getTime());
							RemoteProtocolInfo rpi = l7ModuleService.queryRemoteProtocolInfo(info);
							try{
								// 成功安装且未启用的才能启用
								// 1 -> 3  安装启用
								// 4 -> 3  启用失败的可以再次启用
								// 5 -> 3  禁用后启用
								// 6 -> 3  禁用失败，仍是启用状态，也要更新成状态
								if(rpi != null && rpi.getStatus() != RemoteProtocolInfo.INSTALL_ERROR && rpi.getStatus() != RemoteProtocolInfo.ENABLE_SUCCESS){
									if(client.module_enableremote(Integer.parseInt(l7_protoc))){
										client.commit();
										info.setStatus(RemoteProtocolInfo.ENABLE_SUCCESS);
										info.setErrorMessage("启用协议成功");
										// 记录启用日志  1 -> 3
										l7ModuleService.updateRemoteProtocolInfo(info);
									}
								}else{
									// 安装不成功的保持原状态  2
								}
							} catch(Exception e){
								info.setStatus(RemoteProtocolInfo.ENABLE_ERROR);    //安装未运行
								info.setErrorMessage("启用协议失败" + e.getMessage());
								// 记录启用日志  1 -> 4  启用失败，表明安装成功
								l7ModuleService.updateRemoteProtocolInfo(info);
							}
							client.close();
						}
					}
				} catch (Exception e) {
					 ExceptionUtils.error(log, "查询协议分析器出错 ", e);
		        }
			}
		}).start();
	}

	/**
	 * 删除L7模块目录
	 * 
	 * @param L7_protoc
	 * @throws Exception
	 */
	public static void delL7Module(L7Module l7module){
//		FileUtils.deleteDirectory(ApmFileUtils.getAbsoluteFile(ApmServer.L7_MODULE_DIR + l7_protoc));
//		L7Module l7module = l7ModuleService.getL7ModuleById(l7_protoc);
		RemoteProtocolInfo info = new RemoteProtocolInfo();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try{
					String server_add = "";
					List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
					if(analyzers != null && analyzers.size() > 0){
						for(Analyzer analyzer:analyzers){
							info.setL7_proto(l7module.getL7_proto());
							info.setVersion(l7module.getVersion());
							info.setAnalyzerId(analyzer.getId());
							RemoteProtocolInfo exist = l7ModuleService.queryRemoteProtocolInfo(info);
							if(exist.getStatus() == RemoteProtocolInfo.DISABLE_SUCCESS){   // 禁用成功的才能删除；禁用不成功的保留记录，已备协议分析器重置
								ZeroClient client = new ZeroClient();
								server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
								client.connect(server_add);
								if(client.module_delremote(l7module.getL7_proto())){
									client.commit();
									client.close();
									l7ModuleService.deleteRemoteProtocolInfo(info); 
								}else{
									//
								}
							} else if(exist.getStatus() == RemoteProtocolInfo.INSTALL_SUCCESS || 
									exist.getStatus() == RemoteProtocolInfo.INSTALL_ERROR ){   // 未启用的可删除
									l7ModuleService.deleteRemoteProtocolInfo(info); 
							} else{
								continue;
							}
						}
					}
				}catch(Exception e){
					ExceptionUtils.error(log, "删除远程协议分析器出错 ", e);
				}
			}
		}).start();
	}

	/**
	 * L7模块的禁用
	 * 
	 * @param L7_protoc
	 * @throws Exception
	 */
	public static void disableL7Module(String l7_protoc) throws Exception {
		L7Module l7module = l7ModuleService.getL7ModuleById(l7_protoc);
//		String destDir = ApmServer.L7_MODULE_DIR + l7_protoc + "/" + l7module.getVersion() + "/" + MODULEXML;
//		// 遍历模块下面的文件夹，可能有删除模块后重新上传的
//		File dirs = new File(ApmServer.L7_MODULE_DIR + l7_protoc);
//		if (dirs.listFiles() != null && dirs.listFiles().length > 1) {
//			int j = 0;
//			for (int i=1; i<dirs.listFiles().length; i++) {
//				int length = dirs.listFiles()[i].getName().compareTo(dirs.listFiles()[j].getName());
//				if (length > 0) {
//					destDir = ApmServer.L7_MODULE_DIR + l7_protoc + "/" + dirs.listFiles()[i].getName() + "/" + MODULEXML;
//					j = i;
//				} else {
//					destDir = ApmServer.L7_MODULE_DIR + l7_protoc + "/" + dirs.listFiles()[j].getName() + "/" + MODULEXML;
//				}
//			} 
//		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try{
//					File file = ApmFileUtils.getAbsoluteFile(destDir);
					String server_add = "";
					List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
					if(analyzers != null && analyzers.size() > 0){
						for(Analyzer analyzer:analyzers){
							ZeroClient client = new ZeroClient();
							server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
							
							RemoteProtocolInfo info = new RemoteProtocolInfo();
							info.setId(UUID.randomUUID().toString());
							info.setL7_proto(l7module.getL7_proto());
							info.setVersion(l7module.getVersion());
							info.setAnalyzerId(analyzer.getId());
							info.setCallTime(Calendar.getInstance().getTime());
							
							RemoteProtocolInfo rpi = l7ModuleService.queryRemoteProtocolInfo(info);
							
							try{
								// 运行正常的才能禁用
								// 3 -> 5  启用的更新成禁用的
								// 4 -> 5  未启用的相当于禁用的
								// 6 -> 5  禁用失败的仍在运行，可以被禁用
								if(rpi != null && (rpi.getStatus() == RemoteProtocolInfo.ENABLE_SUCCESS 
										        || rpi.getStatus() == RemoteProtocolInfo.ENABLE_ERROR 
										        || rpi.getStatus() == RemoteProtocolInfo.DISABLE_ERROR )){
									client.connect(server_add);
									if(client.module_disenableremote(Integer.valueOf(l7_protoc))){
										client.commit();
										// 禁用成功   3/6 -> 5
										info.setStatus(RemoteProtocolInfo.DISABLE_SUCCESS);
										info.setErrorMessage("禁用协议成功");
										l7ModuleService.updateRemoteProtocolInfo(info);
									}
								}else{
									// 什么也不做 除3或6以外的状态都不更新
								}
							} catch(Exception e){
								info.setStatus(RemoteProtocolInfo.DISABLE_ERROR);   //   3/6 -> 6   表明启动成功，协议分析器仍在运行
								info.setErrorMessage("禁用协议失败" + e.getMessage());
								l7ModuleService.updateRemoteProtocolInfo(info);
							}
							client.close();
						}
					}
				} catch(Exception e){
					 ExceptionUtils.error(log, "查询协议分析器出错 ", e);
				}
			}
		}).start();
	}

	/**
	 * 设置L7协议
	 * 
	 * @param serviceId
	 * @throws Exception
	 */
	public static void setL7Module(int l7_protoc, String... serviceIds) throws ApmDataIndicatorException {
		for (String serviceId : serviceIds) {
			try{
				ZeroClient client = new ZeroClient();
				Service service = null;
				if (serviceId.contains("-")) {
					service = serviceService.getServiceById(serviceId);
				} else {
					service = serviceService.getDisServiceById(serviceId);
				}
				List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
				if(analyzers != null && analyzers.size() > 0){
					for(Analyzer analyzer:analyzers){
						client.connect("tcp://" + analyzer.getIp() + ":" + analyzer.getPort());
						client.l7_set(service.getL4protocol(), IPUtils.toLittleEndianInteger(service.getIp()), service.getPort(),
								l7_protoc);
						client.commit();
					}
				}
				client.close();
			} catch (Exception e) {
				ExceptionUtils.error(log, "协议分析器设置L7层协议失败", e);
				throw new ApmDataIndicatorException("协议分析器设置L7层协议失败", e);
			} 
		}
	}
	
	/**
	 * 设置L7协议 单个
	 * 
	 * @param serviceId
	 * @throws Exception
	 */
	public static void setL7Module(int l4_protoc, int l7_protoc, String ip, int port) throws ApmDataIndicatorException {
		try (ZeroClient client = new ZeroClient()) {
			List<Analyzer> analyzers = analyzerService.getAllAnalyzerNoPage();
			if(analyzers != null && analyzers.size() > 0){
				for(Analyzer analyzer:analyzers){
					client.connect("tcp://" + analyzer.getIp() + ":" + analyzer.getPort());
					client.l7_set(l4_protoc, IPUtils.toLittleEndianInteger(ip), port,
							l7_protoc);
					client.commit();
				}
			}
		} catch (Exception e) {
			ExceptionUtils.error(log, "协议分析器设置L7层协议失败", e);
			throw new ApmDataIndicatorException("协议分析器设置L7层协议失败:" + e.getMessage(), e);
		} 
	}
	/**
	 * 数据包过滤
	 * 
	 * @throws Exception
	 */
	public static void filterPackage(String analyzerId) throws ApmDataIndicatorException{
		
//		ConfigItem defaultConfig = configItemService.getConfigItem("filter.default_policy");
		
		try (ZeroClient client = new ZeroClient()){
			Analyzer analyzer = analyzerService.getAnalyzerById(analyzerId);
			String server_add = "tcp://" + analyzer.getIp() + ":" + analyzer.getPort();
			client.connect(server_add);
			client.filter_clear();  
			List<FilterRule> rules = configItemService.getAllFiltersJson(analyzerId);
			if (rules != null && rules.size() > 0) {
				for (FilterRule rule : rules) {
					client.filter_add(0, rule.getsIp(), rule.getsPort(), rule.getdIp(), rule.getdPort(), "ACCEPT".equals(rule.getPolicys()));
				}
			}
//			client.filter_setdefault("ACCEPT".equals(defaultConfig.getValue()));
			client.commit();
		} catch (Exception e) {
			ExceptionUtils.error(log, "协议分析器数据包规则保存失败", e);
			throw new ApmDataIndicatorException("协议分析器数据包规则保存失败", e);
		} 
	}

	public static String getProtocolVersion(String server_add) throws ApmDataIndicatorException {
		String version = null;
		try (ZeroClient client = new ZeroClient()){
			client.connect(server_add);
			version = client.print_version();
			if(version != null && version.contains(" ")) {
			    version = version.substring(0,version.indexOf(" ")).trim();
			}
			if (version == null)
				throw new ApmDataIndicatorException("协议分析器版本获取失败，检查是否可以连接到协议分析器：" + server_add);
		} catch (Exception e) {
			ExceptionUtils.error(log, "协议分析器版本获取失败", e);
			throw new ApmDataIndicatorException("协议分析器版本获取失败", e);
		} 
		return version;
	}
	
	public static File getZip(L7Module module, String tempPath) throws Exception{
		
		String fileName = module.getName() + ".mod";
		String destPath = tempPath + "/" + fileName;
		String zipPath = ApmServer.L7_MODULE_DIR + module.getL7_proto() + "/" + module.getVersion();
		
		File dirs = new File(ApmServer.L7_MODULE_DIR + module.getL7_proto());
		for (File childFile : dirs.listFiles()) {
			String filename = childFile.getName();
			long temp = 0l;
			if (filename.trim().length() > module.getVersion().trim().length()) {
				filename = filename.substring(module.getVersion().length(), filename.length());
				temp = Long.valueOf(filename) > temp ? Long.valueOf(filename) : temp;
				zipPath = ApmServer.L7_MODULE_DIR + module.getL7_proto() + "/" + childFile.getName();
			}
		}
		ZipUtil.zip(zipPath, destPath, null);
		return ApmFileUtils.getAbsoluteFile(destPath);
	}
}
